/**
 * Alipay.com Inc.
 * Copyright (c) 2004-2022 All Rights Reserved.
 */
package com.example.spider.proxy.provider.deprecated.mimvp;

import cn.hutool.core.util.ReUtil;
import com.example.spider.proxy.core.ProxyInfo;
import com.example.spider.proxy.core.tester.ProxyTypeEnum;
import com.example.spider.proxy.provider.AbstractProxyResultHandler;
import com.example.spider.proxy.provider.IpProxySpiderTask;
import com.example.spider.starter.SpiderStarter;
import com.example.spider.task.SpiderTaskQueue;
import com.example.spider.util.HtmlUtil;
import org.shoulder.core.converter.LocalDateTimeConverter;

import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author lym
 * @deprecated 2023.4 该网站已关闭，固定返回 301 https://www.google.com/?proxy={in_hp}
 * https://proxy.mimvp.com/freeopen?proxy=in_hp
 * 只能看到第一页ip 【只有一页】
 * 3位port后面补2个 O0O
 * 4位port后面补1个 O0O
 * 2位port后面不补任何字符
 */
//@Component
public class MimvpResultHandler extends AbstractProxyResultHandler implements SpiderStarter {

    private static final char[] firstMap = new char[]{'A', 'E', 'I', 'M', 'Q', 'U', 'Y', 'c', 'g', 'k'};

    private static final char[] secondMap = new char[]{'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5'};

    // 3位端口号规则比较特殊,区分大小写
    // MA-MP 都是0 （16位）； MQ-Mf 都是1（16位）；Mg-Mv 都是2；Mw-Mz 都是3；NA-NP 4    NQ-Nf 5  Ng-Nv 都是6   Nw-Nz 7  OA-OP 8 OQ-Of

    private final String[] condition1 = {"proxy=in_hp", "proxy=in_tp", "proxy=in_socks", "proxy=out_hp", "proxy=out_tp", "proxy=out_socks"};

    private final String[] condition2 = {"sort=p_id", "sort=p_ip", "sort=p_port", "sort=p_type", "sort=p_country", "sort=p_ping", "sort=p_transfer", "sort=p_checkdtime"};

    public MimvpResultHandler() {
        super("mimvp");
    }

    public static Integer recognizeImageIdToPort(String imageId) {
        String result = "";
        // 第一位
        char firstChar = imageId.charAt(0);
        for (int i = 0; i < firstMap.length; i++) {
            if (firstMap[i] == firstChar) {
                result += i;
                break;
            }
        }
        if (result.length() != 1) {
            throw new RuntimeException("unknown input(" + imageId + ") on stage1 for " + firstChar);
        }
        // 第二位
        char secondChar = imageId.charAt(1);
        for (int i = 0; i < secondMap.length; i++) {
            if (secondMap[i] == secondChar) {
                result += i;
                break;
            }
        }
        if (result.length() != 2) {
            throw new RuntimeException("unknown input(" + imageId + ") on stage2 for " + secondChar);
        }
        if (imageId.length() == 2) {
            // 2位数的 ip
            return Integer.valueOf(result);
        }
        // 第三位
        char thirdChar = imageId.charAt(2);
        char forthChar = imageId.charAt(3);
        int thirdDigest = -1;
        // MA-MP 都是0 （16位）； MQ-Mf 都是1（16位）；Mg-Mv 都是2；Mw-Mz 都是3；NA-NP 4    NQ-Nf 5  Ng-Nv 都是6   Nw-Nz 7  OA-OP 8 OQ-Of
        switch (thirdChar) {
            case 'M':
                thirdDigest = forthChar < 'P' ? 0 : forthChar < 'f' ? 1 : forthChar < 'v' ? 2 : 3;
                break;
            case 'N':
                thirdDigest = forthChar < 'P' ? 4 : forthChar < 'f' ? 5 : forthChar < 'v' ? 6 : 7;
                break;
            case 'O':
                thirdDigest = forthChar < 'P' ? 8 : forthChar < 'f' ? 9 : -1;
                break;
            default:
                throw new RuntimeException("unknown input(" + imageId + ") on stage3[0] for " + thirdChar);
        }
        result += thirdDigest;
        if (result.length() != 3) {
            throw new RuntimeException("unknown input(" + imageId + ") on stage3 for " + thirdChar);
        }
        if (imageId.endsWith("O0OO0O")) {
            // 3位数的 ip
            return Integer.valueOf(result);
        }
        // 第四位
        char forthPart = imageId.charAt(4);
        for (int i = 0; i < firstMap.length; i++) {
            if (firstMap[i] == forthPart) {
                result += i;
                break;
            }
        }
        if (result.length() != 4) {
            throw new RuntimeException("unknown input(" + imageId + ") on stage4 for " + forthChar);
        }
        if (imageId.endsWith("O0O")) {
            // 4位数的 ip
            return Integer.valueOf(result);
        }
        // 第五位
        char fifthChar = imageId.charAt(5);
        for (int i = 0; i < secondMap.length; i++) {
            if (secondMap[i] == fifthChar) {
                result += i;
                break;
            }
        }
        if (result.length() != 5) {
            throw new RuntimeException("unknown input(" + imageId + ") on stage5 for " + fifthChar);
        }
        return Integer.valueOf(result);
    }

    @Override
    public void startSpiders() {
        String baseUrl = "https://proxy.mimvp.com/freeopen";
        triggerTask(baseUrl);

        for (String c : condition1) {
            triggerTask(baseUrl + "?" + c);
        }

        for (String c : condition2) {
            triggerTask(baseUrl + "?" + c);
        }

        for (String c1 : condition1) {
            for (String c2 : condition2) {
                triggerTask(baseUrl + "?" + c1 + "&" + c2);
            }
        }
    }

    public void triggerTask(String url) {
        IpProxySpiderTask task = createTask(url);
        task.getHeaders().put("authority", "proxy.mimvp.com");
        SpiderTaskQueue.putTask(task);
    }

    /**
     * 每 10 分钟触发一次
     */
    @Override
    public String executeCron() {
        return "0 0/10 * * * ?";
    }

    protected Duration defaultLimitRateDuration() {
        return Duration.ofSeconds(3);
    }

    /**
     *
     */
    @Override
    public void doHandle(IpProxySpiderTask task, String html) {

        List<String> ipList = ReUtil.findAllGroup1("<tr><td class='free-proxylist-tbl-proxy-id color-blue'>\\d+</td><td class='free-proxylist-tbl-proxy-ip'>(.*?)</td>", html);
        List<String> portStrList = ReUtil.findAllGroup1("<td class='free-proxylist-tbl-proxy-port'><img src=(.*?) /></td>", html);
        List<String> typeList = ReUtil.findAllGroup1("<td class='free-proxylist-tbl-proxy-type' title='.*?'>(.*?)</td>", html);
        List<String> locationList = ReUtil.findAllGroup1("<td class='free-proxylist-tbl-proxy-country'><img src='.*?' alt='.*?'>(.*?)</td>", html);
        List<String> responseTimeList = ReUtil.findAllGroup1("<td class='free-proxylist-tbl-proxy-pingtime' title='(.*?)秒'><div class='time_bgcolor'><span .*?</span></div></td>", html);
        List<String> speedList = ReUtil.findAllGroup1("<td class='free-proxylist-tbl-proxy-transfertime' title='(.*?)秒'><div class='time_bgcolor'><span .*?></span></div></td>", html);
        List<String> lastVerificationTimeList = ReUtil.findAllGroup1("<td class='free-proxylist-tbl-proxy-checkdtime'>(.*?)</td></tr>", html);

        List<Integer> portList = portStrList.parallelStream()
                .map(portImageIdStr ->
                        // 5 = "port=".length(); 15 等于前14个固定字符 + 第15个固定D（代表数字）
                        portImageIdStr.substring(portImageIdStr.lastIndexOf("port=") + 5 + 15)
                )
                .map(MimvpResultHandler::recognizeImageIdToPort)
                .collect(Collectors.toList());

        for (int i = 0; i < ipList.size(); i++) {
            ProxyInfo proxyInfo = ProxyInfo.builder()
                    .source(taskName)
                    .ip(ipList.get(i))
                    .port(portList.get(i))
                    .anonymity(task.getUrl().contains("_tp") ? "普通" : "高匿")
                    .proxyTypeEnum(ProxyTypeEnum.of(typeList.get(i)))
                    .type(ProxyTypeEnum.of(typeList.get(i)).getType())
                    .location(HtmlUtil.removeAllHtmlTag(locationList.get(i)))
                    .responseTime(ProxyInfo.parseSecondToMill(responseTimeList.get(i)))
                    .lastVerificationTime(
                            LocalDateTimeConverter.INSTANCE.convert(lastVerificationTimeList.get(i))
                    )
                    .build();
            // 保存到文件
            addProxyToSourceRepository(proxyInfo);
        }
    }


    /**
     * 历史数据兼容
     */
//    public void processMimvpPort() {
//        existProxyInfos.forEach(p -> {
//            Map<String, String> ext = p.getExtendInfo();
//            if (MapUtil.isNotEmpty(ext)) {
//                String portImageId = ext.get("portImageId");
//                portImageId = portImageId.substring(portImageId.lastIndexOf("port=") + 6 + 14);
//                Integer port = MimvpResultHandler.recognizeImageIdToPort(portImageId);
//                if (port != null) {
//                    p.setPort(port);
//                    ext.remove("portImageId");
//                    memoryVersion.increment();
//                }
//            }
//        });
//    }

}